﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using FluentPS.Attributes;
using FluentPS.Enums;

namespace FluentPS.Extensions
{
    public static class TypeExtensions
    {
        public static PSEntityType GetPSEntityType(this Type type)
        {
            var attr = type.GetClassCustomAttribute<PSEntityTypeAttribute>();
            if (attr != null)
                return attr.EntityType;

            throw new ArgumentException(string.Format("Unable to find {0} attribute for class {1}", typeof(PSEntityTypeAttribute), type));
        }

        public static T GetPropertyCustomAttribute<T>(this Type type, PropertyInfo propertyInfo) where T : Attribute
        {
            object[] customAttributes = propertyInfo.GetCustomAttributes(typeof(T), true);
            if (customAttributes.Length > 0)
            {
                return (T)customAttributes[0];
            }

            return null;
        }

        public static T GetCustomAttribute<T>(this PropertyInfo propertyInfo) where T : Attribute
        {
            object[] customAttributes = propertyInfo.GetCustomAttributes(typeof(T), true);
            if (customAttributes.Length > 0)
            {
                return (T)customAttributes[0];
            }

            return null;
        }

        public static T GetClassCustomAttribute<T>(this Type type) where T : Attribute
        {
            foreach (var attr in type.GetCustomAttributes(typeof(T), false))
            {
                if (attr is T)
                    return attr as T;
            }
            return null;
        }

        public static void ForeachProperty(this Type type, Action<PropertyInfo> action)
        {
            if (action != null)
                foreach (PropertyInfo propertyInfo in type.GetProperties())
                    action(propertyInfo);
        }

        public static bool IsEnumerableGeneric(this Type type)
        {
            return type.IsGenericType &&
            type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
        }

        public static IList CreateGenericList(this Type type)
        {
            Type genericType = typeof(List<>).MakeGenericType(new[] { type });
            return (IList)Activator.CreateInstance(genericType);
        }

    }
}
